#pragma once

#include "noncopyable.h"
#include "Timestamp.h"

#include <functional>
#include <memory>

/// @brief 不直接引用对应头文件而使用前置声明，而在源文件中才进行引用对应的头文件，便于减少类信息的裸露
class EventLoop;

/**
 * @brief Channel 为通道，封装sockfd，event，以及绑定对应的回调函数
 *
 */
class Channel : noncopyable
{
public:
    using EventCallback = std::function<void()>;
    using ReadEventCallback = std::function<void(Timestamp)>;

    Channel(EventLoop *loop, int fd);
    ~Channel();

    void handlEvent(Timestamp receiveTime);

    // 设置事件处理回调函数
    void setReadCallback(ReadEventCallback cb)
    {
        readCallback_ = std::move(cb);
    }
    void setWriteCallback(EventCallback cb)
    {
        writeCallback_ = std::move(cb);
    }
    void setCloseCallback(EventCallback cb)
    {
        closeCallback_ = std::move(cb);
    }
    void setErrorCallback(EventCallback cb)
    {
        errorCallback_ = std::move(cb);
    }

    void tie(const std::shared_ptr<void> &);

    int fd() const
    {
        return fd_;
    }
    int events() const
    {
        return events_;
    }
    void set_revents(int revt)
    {
        revents_ = revt;
    }
    // 设置关注fd的事件状态
    void enableReading()
    {
        events_ |= kReadEvent;
        update();
    }
    void disableReading()
    {
        events_ &= ~kReadEvent;
        update();
    }
    void enableWriting()
    {
        events_ |= kWriteEvent;
        update();
    }
    void disableWriting()
    {
        events_ &= ~kWriteEvent;
        update();
    }
    void disableAll()
    {
        events_ = kNoneEvent;
        update();
    }
    // 判断当前的事件状态（二进制标志位判断）
    bool isNoneEvent() const
    {
        return events_ == kNoneEvent;
    }
    bool isReading() const
    {
        return events_ & kReadEvent;
    }
    bool isWriting() const
    {
        return events_ & kWriteEvent;
    }
    int index()
    {
        return index_;
    }
    void set_index(int idx)
    {
        index_ = idx;
    }
    EventLoop *ownerLoop()
    {
        return loop_;
    }

    void remove();

private:
    // 更新分发器上对应fd的关注的事件
    void update();
    void handleEventWithGuard(Timestamp receiveTime);

    static const int kNoneEvent;
    static const int kReadEvent;
    static const int kWriteEvent;

    EventLoop *loop_; // 事件循环-通过找到循环，从而操作事件分发器
    const int fd_;    // sockfd
    int events_;      // 关注的事件
    int revents_;     // 就绪的事件
    int index_;

    std::weak_ptr<void> tie_;
    bool tied_;

    // fd绑定的回调函数
    ReadEventCallback readCallback_;
    EventCallback writeCallback_;
    EventCallback closeCallback_;
    EventCallback errorCallback_;
};